package com.duguo.dynamicmvc.support.servlet;

import java.io.IOException;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.ListableBeanFactory;

import com.duguo.dynamicmvc.factory.ControllerBuilder;
import com.duguo.dynamicmvc.factory.utils.BeanFactoryUtils;

public abstract class AbstractDynamicMVC{

	private static Log _log = LogFactory.getLog(AbstractDynamicMVC.class);
	private RequestHandler _requestHandler;
	private ServletContext _servletContext;
	private ListableBeanFactory _beanFactory;

	protected abstract ListableBeanFactory createBeanFactory();

	protected abstract void destroyBeanFactory();
	
	public void init(ServletContext servletContext) throws ServletException {
		_servletContext=servletContext;
		try{
			_beanFactory=createBeanFactory();
			ControllerBuilder controllerBuilder=BeanFactoryUtils.getBeanOfType(_beanFactory, ControllerBuilder.class);
    		controllerBuilder.build();
    		_requestHandler=BeanFactoryUtils.getBeanOfType(_beanFactory, RequestHandler.class);
    	}catch(Throwable ex){
    		_log.error("Failed to start", ex);
    		throw new ServletException("Failed to start", ex);
    	}
	}

	public void service(ServletRequest req, ServletResponse res) throws IOException, ServletException {
		HttpServletRequest request=(HttpServletRequest)req;
		HttpServletResponse response=(HttpServletResponse)res;
		try {
			_requestHandler.handleRequest(request, response);
		} catch (NotFoundException e) {
			response.sendError(HttpServletResponse.SC_NOT_FOUND);
		}catch (Exception e) {
			_log.error(e.getMessage(),e);
			response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
		}
	}

	public void destroy() {
		destroyBeanFactory();
	}

	public ListableBeanFactory getBeanFactory() {
		return _beanFactory;
	}

	public void setBeanFactory(ListableBeanFactory beanFactory) {
		this._beanFactory = beanFactory;
	}

	public ServletContext getServletContext() {
		return _servletContext;
	}

}
